package cc.liyinghao.springsecuritydemo.service;

import cc.liyinghao.springsecuritydemo.mapper.RolePermissionMapper;
import cc.liyinghao.springsecuritydemo.mapper.UserMapper;
import cc.liyinghao.springsecuritydemo.mapper.UserRoleMapper;
import cc.liyinghao.springsecuritydemo.pojo.UserRole;
import cc.liyinghao.springsecuritydemo.pojo.bo.UserDetail;
import cc.liyinghao.springsecuritydemo.pojo.User;
import cc.liyinghao.springsecuritydemo.pojo.param.UserRegisterParam;
import cc.liyinghao.springsecuritydemo.security.util.JwtTokenUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;

@Service
@Slf4j
@RequiredArgsConstructor
public class UserService {

    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder;
    private final JwtTokenUtil jwtTokenUtil;
    private final UserRoleMapper userRoleMapper;
    private final RolePermissionMapper rolePermissionMapper;

    public User register(UserRegisterParam userRegisterParam) {
        User user = new User();
        BeanUtils.copyProperties(userRegisterParam, user);
        user.setCreatedAt(LocalDateTime.now());
        user.setEnabled(true);
        //将密码加密
        String encodePassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodePassword);
        userMapper.insert(user);
        return user;
    }

    /**
     * 登录接口，返回token
     */
    public String login(String username, String password) {
        String token = null;
        try {
            UserDetails userDetails = loadUserByUsername(username);
            if (!passwordEncoder.matches(password, userDetails.getPassword())) {
                throw new RuntimeException("用户名或密码错误");
            }
            //生成AuthenticationToken，目的是将用户信息放入SecurityContextHolder中
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            //将authentication放入SecurityContextHolder中
            SecurityContextHolder.getContext().setAuthentication(authentication);
            //生成token
            token = jwtTokenUtil.generateToken(userDetails);
        } catch (AuthenticationException e) {
            log.error("登录异常:{}", e.getMessage());
        }
        return token;
    }

    /**
     * 根据用户名获取用户信息，命名属于属于spring security开发规范
     * 之后会在security通过重写注入调用
     */
    public UserDetails loadUserByUsername(String username) {
        // 获取登录用户信息
        User user = getSysUserByUsername(username);
        // 用户不存在
        if (BeanUtil.isEmpty(user)) {
            throw new RuntimeException("用户不存在");
        }
        //用户停用
        if (!user.getEnabled()) {
            throw new RuntimeException("用户已停用");
        }
        int userId = user.getId();
        // 获取角色
        Set<String> roles = userRoleMapper.getListRoleKeyByUserId(userId);
        // 权限列表
        Set<String> permissions =
                rolePermissionMapper.getListPermissionKeyByRoleId(userId);
        return new UserDetail(user, roles, permissions);
    }

    public User getSysUserByUsername(String username) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        return userMapper.selectOne(queryWrapper);
    }

}
